package cn.shiwei.hr.service.impl;

import cn.shiwei.hr.domain.Login;
import cn.shiwei.hr.domain.VipBase;
import cn.shiwei.hr.domain.VipUser;
import cn.shiwei.hr.dto.LoginMealDto;
import cn.shiwei.hr.dto.RegisterDTO;
import cn.shiwei.hr.fegin.auth.LoginFeginClient;
import cn.shiwei.hr.mapper.VipUserMapper;
import cn.shiwei.hr.repository.AjaxResult;
import cn.shiwei.hr.repository.AssertUtil;
import cn.shiwei.hr.service.IVipBaseService;
import cn.shiwei.hr.service.IVipUserService;
import cn.shiwei.hr.to.SMSCodeTO;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import javax.validation.constraints.NotEmpty;

import static cn.shiwei.hr.constants.BaseConstants.Login.TYPE_ACCOUNT_BACKSTAGE;
import static cn.shiwei.hr.constants.BaseConstants.Login.TYPE_ACCOUNT_FRONTDESK;
import static cn.shiwei.hr.constants.VerifyConstants.SIGN__SMS_VERIFY;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author 1363732197@qq.com
 * @since 2021-12-02
 */
@Service
public class VipUserServiceImpl extends ServiceImpl<VipUserMapper, VipUser> implements IVipUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LoginFeginClient loginFeginClient;

    @Autowired
    private IVipBaseService vipBaseService;


    @GlobalTransactional // 开启全局事务
    @Override
    public void register(RegisterDTO registerDTO) {
        // 校验参数, 通过注解已完成
        String mobile = registerDTO.getMobile();

        // 校验手机号是否被注册
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("phone", registerDTO.getMobile());

        VipUser vipUser = super.selectOne(wrapper);

        AssertUtil.noNull(vipUser, "手机号已注册, 请直接登录");

        // 校验验证码
        String signSMSVerify = String.format(SIGN__SMS_VERIFY, registerDTO.getMobile());
        SMSCodeTO smsCodeTo = (SMSCodeTO)redisTemplate.opsForValue().get(signSMSVerify);

        String smsCode = smsCodeTo.getSmsCode();
        AssertUtil.stringIsEmpty(smsCode, "短信验证过期");
        AssertUtil.isTrue(smsCode.equalsIgnoreCase(registerDTO.getSmsCode()), "手机验证码错误");

        VipUser user = getInitVipUser(registerDTO.getMobile(), registerDTO.getPassword());
        // 保存用户信息
        super.insert(user);

        Login login = getInitLogin(registerDTO.getMobile(), user.getPassword(), TYPE_ACCOUNT_FRONTDESK);

        // 生成并保存login
        AjaxResult ajaxResult = loginFeginClient.saveLoginAndMeal(new LoginMealDto(login, null));
        if (!ajaxResult.isSuccess() || ajaxResult.getResultObj() == null) { // 如果为操作成功(没降级)
            throw new RuntimeException("保存用户登录信息失败");
        }

        VipBase vipBase = getInitVipBase(login.getId(), registerDTO.getRegChannel());
        vipBaseService.insert(vipBase);

        user.setLoginId(login.getId());
        super.updateById(user); // 关联外键

        redisTemplate.delete(signSMSVerify);

    }

    // 初始化方法
    private VipUser getInitVipUser(String phone, String password){
        VipUser vipUser = new VipUser();
        vipUser.setPhone(phone);
        vipUser.setCreateTime(System.currentTimeMillis());
        vipUser.setSalt("");
        vipUser.setPassword(password);
        vipUser.setSecLevel(0);
        return vipUser;
    }

    // 初始化方法
    private Login getInitLogin(String phone, String password, int state){
        Login login = new Login();
        login.setUsername("新用户" + phone);
        login.setPassword(password);
        login.setType(state);
        login.setEnabled(true);
        login.setAccountNonExpired(true);
        login.setAccountNonLocked(true);
        login.setCredentialsNonExpired(true);
        return login;
    }

    // 初始化方法
    private VipBase getInitVipBase(Long loginId, int regChannel){
        long time = System.currentTimeMillis();
        VipBase vipBase = new VipBase();
        vipBase.setCreateTime(time);
        vipBase.setSsoId(loginId);
        vipBase.setRegChannel(regChannel);
        vipBase.setRegTime(time);
        vipBase.setLevel(0);
        vipBase.setGrowScore(0);
        return vipBase;
    }
}
